<template>
  <h1 class="title">SimpleAI</h1>
  <div class="main" ref="main">
    <div class="message-panel">
      <template v-for="(item, index) in messageList" :key="index">
        <div class="sender" v-if="item.type==0">
          <p class="question">{{item.content}}</p>
        </div>
        <div class="reply" v-if="item.type==1">
          <div class="avatar">
            <img src="./th.jpg" alt="Avatar" width="18" height="18">
          </div>
          <MdPreview previewTheme="vuepress" :codeFoldable="false" :modelValue="item.content.join('')" />
        </div>
      </template>
    </div>
  </div>
  <div class="input-container">
    <div class="input-area">
      <input class="input" type="text" placeholder='给"SimpleAI"发送消息' v-model="content">
      <img src="./assets/send.svg" class="btn" alt="send" @click="onSend" v-if="!isLoading"/>
      <Loading class="loading" v-else></Loading>
    </div>
  </div>
</template>
<script setup>
import { ref, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import Loading from './components/Loading.vue';

const isLoading = ref(false)
const content = ref('')
const messageList = ref([])
const main = ref(null)
const BASE_URL = 'http://localhost:10024'

if(localStorage.getItem('messageList')){
  messageList.value = JSON.parse(localStorage.getItem('messageList'))
}
const scrollToBottom = () => {
  setTimeout(() => {
    nextTick(() => {
      main.value.scrollTop = main.value.scrollHeight
    })
  }, 1);
}
const onSend = () => {
  if (!content.value.trim()) {
    ElMessage({
      type: 'warning',
      message: '请输入内容',
    })
    return
  }
  messageList.value.push({
    type: 0,
    content: content.value,
  })
  messageList.value.push({
    type: 1,
    content: [],
    loading: true,
  })
  isLoading.value = true
  const eventSource = new EventSource(`${BASE_URL}/api/stream?message=${content.value}`)
  console.log(`${BASE_URL}/api/stream?message=${content.value}`)
  content.value = ''
  eventSource.onmessage = (event) => {
    let response = event.data
    console.log(response)
    if (response == '[DONE]') {
      close()
      return
    }
    const parsed = JSON.parse(response)
    if(parsed.error){
      const errorString = `!!! error 连接异常，请稍后再试\n错误原因:${parsed.error}`
      const content = messageList.value[messageList.value.length - 1].content
      messageList.value[messageList.value.length - 1].content = [...content, '\n', ...errorString]
      close()
      return
    }
    messageList.value[messageList.value.length - 1].content.push(parsed.content)
    window.localStorage.setItem('messageList', JSON.stringify(messageList.value))
    scrollToBottom()
  }
  eventSource.onerror = (e) => {
    close()
    ElMessage({
      type: 'error',
      message: '连接失败',
    })
    const errorString = `!!! error 连接异常，请稍后再试\n错误原因:${e.message}`
    messageList.value[messageList.value.length - 1].content = [...errorString]
    scrollToBottom()
  }
  const close = () => {
    eventSource.close()
    messageList.value[messageList.value.length - 1].loading = false
    isLoading.value = false
  }
}
</script>
<style scoped>
.title{
  position: fixed;
  top: 0;
  width: 100%;
  text-align: center;
  font-size: larger;
  padding: 1.6rem 0;
  background-color: #fff;
  height: 6rem;
}
.main{
  position: fixed;
  width: 100%;
  top: 4rem;
  height: calc(100vh - 14rem);
  overflow-y: scroll;
}

.message-panel{
  width: 50vw;
  margin: 0 auto;
}

@media (max-width: 768px) {
    .message-panel {
      width: calc(100vw - 4rem);
    }
}

.sender{
  display: flex;
  justify-content: flex-end;
}
.question{
  border-radius: 2rem;
  background-color: #f2f2f2f2;
  padding: 0.6rem 1.2rem;
  margin: 0.6rem;
}

.reply{
  display: flex;
}
.avatar{
  margin-top: 1.4rem;
  border: 1px solid #f2f2f2;
  padding: 0.5em;
  border-radius: 2rem;
  display: flex;
  place-content: center;
  width:min-content;
  height:min-content;
}

.input-container{
  position: fixed;
  bottom: 2rem;
  width: 100%;
}

.input-area{
  width: 50vw;
  margin: 0 auto;
  min-height: 6rem;
  border-radius: 1.6rem;
  background-color: #efefef;
  padding: 1rem 1.6rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

@media (max-width: 768px) {
    .input-area {
      width: calc(100vw - 4rem);
      margin: 0 auto;
      min-height: 6rem;
      border-radius: 1.6rem;
      background-color: #efefef;
      padding: 1rem 1.6rem;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }
}
.input{
  display: block;
  border: none;
  outline: none;
  background-color: #efefef;
  font-size: medium;
  width: 100%;
}
.btn{
  align-self: flex-end;
  background-color: #000;
  color: #f2f2f2;
  border: none;
  font-size: x-small;
  width: 2.4rem;
  height: 2.4rem;;
  border-radius: 2rem;
  padding: 0.4rem;
  padding-bottom: 0.6rem;
  margin: 0 0.4rem;

}
.btn:hover{
  background-color: #3d3d3d;
}

.loading{
  align-self: flex-end;
  margin-bottom: 0.4rem;
}
</style>
